package cky_parser;

import java.util.*;

public class CKYTable
{
	Grammar grm;
	public String[] words;										//Words separated from the original sentence
	int iIndex, jIndex, kIndex;							//row, column, bias index
	//public boolean status;								//false if new word, true of found a grammar
	public String statusLabel;
	
	Cell[][] elements;
	int leftX, leftY, belowX, belowY, centerX, centerY;	//The coordinate of the focused cells
	int leftActiveIndex, belowActiveIndex, centerActiveIndex;
	public ArrayList<Phrase> phraseList;
	
	int totalOrder;
	public int totalOrderIndex;
	
	public CKYTable (String sentence, Grammar grammar)
	{
		grm = grammar;
		//activeCell = new Cell[3];
		separateWord(sentence);

		//Initiate the elements matrix
		elements = new Cell[words.length][];
		for (int i = 0; i< words.length; i++) elements[i] = new Cell[words.length];
		for (int i = 0; i< words.length; i++)
			for (int j = 0; j< words.length; j++) elements[i][j] = new Cell(i, j);
				
		statusLabel = "";
		jIndex = 0;
		iIndex = 0;
		phraseList = new ArrayList<Phrase>();
		
		totalOrder = 0;
		totalOrderIndex = -1;
	}
	
	void separateWord (String sentence)
	{
		words = sentence.split(" ");
	}
	
	
	
	public void Process()
	{
		for (jIndex = 0; jIndex < words.length; jIndex++)
		{
			ArrayList<String> newWord = grm.checkDictionary(words[jIndex]);
			
			for (int i = 0; i< newWord.size(); i++)
			{
				Phrase combination = new Phrase(newWord.get(i), totalOrder++);
				phraseList.add(combination);
				elements[jIndex][jIndex].add(combination);
				
			}
			
			for (iIndex = jIndex - 1; iIndex >= 0; iIndex--)
			{
				for (kIndex = iIndex + 1; kIndex <= jIndex; kIndex++)
				{
					Cell leftCell = elements[iIndex][kIndex - 1];
					Cell belowCell = elements[kIndex][jIndex];
					
					for (int i = 0; i< leftCell.phrases.size(); i++)
						for (int j = 0; j< belowCell.phrases.size(); j++)
						{
							String[] rule = new String[]{leftCell.phrases.get(i).Value, belowCell.phrases.get(j).Value};
							String result = grm.checkGrammar(rule);
							if (result != "")
							{
								Phrase combination = new Phrase(result, iIndex, kIndex - 1, i, kIndex, jIndex, j, totalOrder++);
								elements[combination.leftCellY][combination.belowCellX].add(combination);
								phraseList.add(combination);
							}
						}
				}
			}
		}
		
	}
	
	public void next()
	{
		if (totalOrderIndex < phraseList.size()) totalOrderIndex++;
		refresh();
	}
	
	public void back()
	{
		if (totalOrderIndex > 1) totalOrderIndex--;
		refresh();
	}
	
	void refresh()
	{
		statusLabel = "";
		Phrase activePhrase = phraseList.get(totalOrderIndex);
		
		for (int i = 0; i< words.length; i++)
			for (int j = i; j< words.length; j++)
			{
				
				if (elements[i][j].phrases.contains(activePhrase))
				{
					elements[i][j].activeIndex = elements[i][j].phrases.indexOf(activePhrase);
					centerX = j;
					centerY = i;
					
				}
				else
				{
					if (i == activePhrase.leftCellY && j == activePhrase.leftCellX)
					{
						elements[i][j].activeIndex = activePhrase.leftCellIndex;
						leftX = j;
						leftY = i;
					}
					else
					{
						if (i == activePhrase.belowCellY && j == activePhrase.belowCellX)
						{
							elements[i][j].activeIndex = activePhrase.belowCellIndex;
							belowX = j;
							belowY = i;
						}
						else
							elements[i][j].activeIndex = -1;
						
					}
				}
			}
		if (activePhrase.isNewWord == true) statusLabel = "'" + words[centerX] +"' is labelled " + activePhrase.Value;
		else statusLabel = "Found an "+activePhrase.Value + "["+leftY+","+leftX+"], ["+belowY+","+belowX+"]";
	}
	/*
	public static void main(String[] args)
	{
		Grammar grm = new Grammar ("C:/Users/Vinh Phat/Desktop/CKY/Grammar", "C:/Users/Vinh Phat/Desktop/CKY/Dictionary");
		CKYTable tab = new CKYTable("the chef eats fish with the chopsticks", grm);
		tab.Process();
		
		for (int i = 0; i< 19; i++) 
			tab.next();
		
		String[] result = tab.getContent(0, 6);
		if (result != null)
			for (int i = 0; i< result.length; i++)
				System.out.println(result[i]);
		//System.out.println(result.length);
		System.out.println(tab.statusLabel);
		int test = 1;
		int a = test;
	}
	*/
	
	public String[] getContent(int row, int column)
	{
		return elements[row][column].getContent(totalOrderIndex);
	}
}

class Cell
{
	int iIndex, jIndex;									//Row, Column Index
	public int activeIndex;									//Index of the active phrase
	//public boolean active;										//True if the cell is focused, false otherwise
	
	public ArrayList<Phrase> phrases;							//Part of speech
	
	public Cell(int i, int j)
	{
		iIndex = i;
		jIndex = j;
		activeIndex = -1;
		phrases = new ArrayList<Phrase>();
	}
	
	public void add(String wordClass, int totalOrder)
	{
		Phrase newPhrase = new Phrase(wordClass, totalOrder);
		phrases.add(newPhrase);
	}
	
	public void add(Phrase newFound)
	{
		newFound.order = 1;
		for (int i = phrases.size() - 1; i >= 0; i--)
			if (phrases.get(i).Value.compareTo(newFound.Value) == 0)
			{
				newFound.order = phrases.get(i).order + 1;
				break;
			}
		
		phrases.add(newFound);
		
	}
	
	public String[] getContent(int totalOrderIndex)
	{
		String line = "";
		ArrayList<String> com = new ArrayList<String>();
		String[] result;
		
		
		for (int i = 0; i< phrases.size() && phrases.get(i).totalOrder <= totalOrderIndex; i++)
		{
			if (com.contains(phrases.get(i).Value))
			{
				com.set(com.indexOf(phrases.get(i).Value), com.get(com.indexOf(phrases.get(i).Value)) + "1");
				
				com.add(phrases.get(i).getContent(true));
			}
			else
			{
				com.add(phrases.get(i).getContent(false));
			}
		}
		
		if (com.size() == 0) return null;
		else
		{
			result = new String[com.size() + 2];
			result[0] = String.valueOf(activeIndex);
			result[1] = "["+iIndex+","+jIndex+"]";
			for (int i = 0;i < com.size(); i++)
				result[i+2] = com.get(i);
			
			return result;
		}
		
		/*
		for (int i = 0; i< com.size(); i++)
			if (i == 0) line += com.get(i);
			else line += " " + com.get(i);
		
		if (line.compareTo("") == 0) return (new String[] {line});
		else return (new String[] {line, "["+iIndex+","+jIndex+"]"});
		*/
	}
}

class Phrase
{
	public String Value;
	public int leftCellX, leftCellY, leftCellIndex;					//Coordinate x, y and the order of the left origin word
	public int belowCellX, belowCellY, belowCellIndex;					//Coordinate x, y and the order of the below origin word
	public int order;
	public boolean isNewWord;
	
	public int totalOrder;
	
	public Phrase (String s, int totalOrder)
	{
		Value = s;
		leftCellX = leftCellY = leftCellIndex = -1;
		belowCellX = belowCellY = belowCellIndex = -1;
		order = 1;
		isNewWord = true;
	}
	
	public Phrase (String s, int leftY, int leftX, int leftIndex, int belowY, int belowX, int belowIndex, int totalOrder)
	{
		Value = s;
		leftCellX = leftX;
		leftCellY = leftY;
		leftCellIndex = leftIndex;
		belowCellX = belowX;
		belowCellY = belowY;
		belowCellIndex = belowIndex;
		this.totalOrder = totalOrder;
		isNewWord = false;
	}
	
	public String getContent(boolean hasOrder)
	{
		if (hasOrder == false) return Value;
		else return Value + order;
	}
}


